package org.chen.scene.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.chen.common.scene.dto.SceneApiConfigDTO;
import org.chen.common.scene.dto.SearchResponse;
import org.chen.common.scene.dto.api.CtripApiRequest;
import org.chen.common.scene.dto.api.CtripApiResponse;
import org.chen.common.result.ResultVO;
import org.chen.common.scene.entity.Attraction;
import org.chen.common.scene.entity.CityCoordinate;
import org.chen.common.scene.entity.District;
import org.chen.common.scene.model.SearchResultItem;
import org.chen.scene.feign.SystemClient;
import org.chen.scene.service.districtid.CtripDistritIdSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;
import java.util.List;
import java.util.Random;
import java.util.UUID;

@Slf4j
@Service
public class CtripApiService {
    
    private static final String CTRIP_API_URL = "https://m.ctrip.com/restapi/soa2/18109/json/getAttractionList";

    @Autowired
    private SystemClient systemClient;

    @Autowired
    private DistrictService districtService;

    @Autowired
    private CtripDistritIdSearchService ctripDistritIdSearchService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String[] USER_AGENTS = {
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"
    };

    private final RestTemplate restTemplate = new RestTemplate();
    
    public CtripApiResponse fetchAttractions(String cityName, Integer index, Integer sortType,
                                             Integer count, List<String> filterItems, String keyword) {
        try {
            ResultVO<SceneApiConfigDTO> sceneApiConfig = systemClient.getSceneApiConfig();
            SceneApiConfigDTO data = sceneApiConfig.getData();
            CtripApiRequest.Head head = new CtripApiRequest.Head();
            head.setCid(data.getCid());
            head.setSid(data.getSid());
            head.setSyscode(data.getSyscode());

            // 构建请求参数
            CtripApiRequest request = new CtripApiRequest();
            request.setHead(head);
            request.setIndex(index);
            request.setSortType(sortType);
            request.setCount(count);
            request.setKeyword(keyword);

            // 设置筛选条件
            CtripApiRequest.Filter filter = new CtripApiRequest.Filter();
            filter.setFilterItems(filterItems != null && !filterItems.isEmpty() ?
                                filterItems : List.of("NULL;NULL"));
            request.setFilter(filter);

            // 获取districtId是通过cityName映射得到的
            District district = districtService.getOne(new QueryWrapper<District>()
                    .eq("district_name", cityName.trim())
            );

            if (district != null && district.getDistrictId() != null) {
                request.setDistrictId(district.getDistrictId());
            } else {
                SearchResponse searchResponse = ctripDistritIdSearchService.searchCity(cityName);
                SearchResultItem searchResultItem = searchResponse.getRstList().get(0);
                Long districtIdFromApi = Long.valueOf(searchResultItem.getDistrictId());
                request.setDistrictId(districtIdFromApi);

                // 安全地保存district信息
                saveDistrictSafely(cityName.trim(), districtIdFromApi);

            }

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("User-Agent", USER_AGENTS[new Random().nextInt(USER_AGENTS.length)]);
            
            HttpEntity<CtripApiRequest> entity = new HttpEntity<>(request, headers);
            
            // 发送请求
            ResponseEntity<CtripApiResponse> response = restTemplate.exchange(
                CTRIP_API_URL, HttpMethod.POST, entity, CtripApiResponse.class);
            
            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                log.info("携程API调用成功，返回景点数量: {}", 
                        response.getBody().getAttractionList() != null ? 
                        response.getBody().getAttractionList().size() : 0);
                return response.getBody();
            } else {
                log.error("携程API调用失败，状态码: {}", response.getStatusCode());
                return null;
            }
            
        } catch (Exception e) {
            log.error("调用携程API异常", e);
            return null;
        }
    }

    private void saveDistrictSafely(String cityName, Long districtId) {
        String lockKey = "district_lock:" + cityName;
        String lockValue = UUID.randomUUID().toString();

        try {
            // 尝试获取锁
            Boolean lockAcquired = redisTemplate.opsForValue()
                    .setIfAbsent(lockKey, lockValue, Duration.ofSeconds(10));

            if (Boolean.TRUE.equals(lockAcquired)) {
                // 再次检查是否存在
                District existing = districtService.getOne(
                        new QueryWrapper<District>().eq("district_name", cityName));

                if (existing == null) {
                    District district = new District();
                    district.setDistrictId(districtId);
                    district.setDistrictName(cityName.trim());
                    districtService.save(district);
                }
            }
        } catch (Exception e) {
            // 释放锁
            String currentValue = redisTemplate.opsForValue().get(lockKey);
            if (lockValue.equals(currentValue)) {
                redisTemplate.delete(lockKey);
            }
        }
    }
}